using System;
using System.Drawing;
using System.ComponentModel;
using System.Collections.Generic;

using SBPweb.Modules.Modularity;
using SBPweb.Modules.Smartparts;

using SBPweb.Controls.Windows.Common;

using TD.SandDock;
using System.Runtime.InteropServices;


namespace SBPweb.Presentation.Windows.Forms.Controls
{
    /// <summary>
    /// Recommended base class of UI elements
    /// </summary>
    [ComVisible(true)]
    [ClassInterface( ClassInterfaceType.AutoDispatch )]
    public partial class DockingUserControl : UserControl, IDockingSmartpart
    {
        #region Private fields

        private DockControl pDockControl = new DockableWindow();

        private System.Windows.Forms.Timer blinkTimer;

        private IModule pParentModule;
        private bool pIsModal;
        private AppearanceStyle pAppearanceStyle = AppearanceStyle.Tabbed;
        private bool mIsWindow = true;
        private BorderStyle mBorderStyle = SBPweb.Modules.Smartparts.BorderStyle.SizableToolWindow;
        private System.Windows.Forms.DockStyle pDockStyle = System.Windows.Forms.DockStyle.Right;
        private Image mOriginalImage;
        private Image mTempImage;

        #endregion

        public static bool EnableTooltips = true;

        #region Constructor logic

        /// <summary>
        /// Default constructor
        /// </summary>
        private DockingUserControl()
        {
            mInitialize();
        }

        /// <summary>
        /// Contructor
        /// </summary>
        /// <param name="parentModule">Parent module</param>
        public DockingUserControl(IModule parentModule)
        {
            pParentModule = parentModule;
            mInitialize();
        }

        private void mInitialize()
        {
            base.Dock = System.Windows.Forms.DockStyle.Fill;

            AllowCollapse = true;
            AllowDockBottom = true;
            AllowDockCenter = true;
            AllowDockLeft = true;
            AllowDockRight = true;
            AllowDockTop = true;
            AllowFloat = true;

            TextChanged += new EventHandler(DockingUserControl_TextChanged);

            DockControl.DockSituationChanged += new EventHandler(DockControl_DockSituationChanged);
            DockControl.Closed += new EventHandler(DockControl_Closed);
            DockControl.Closing += new DockControlClosingEventHandler(DockControl_Closing);
            DockControl.Disposed += new EventHandler(DockControl_Disposed);

            base.VisibleChanged += new EventHandler(DockingUserControl_VisibleChanged);
            base.EnabledChanged += new EventHandler(DockingUserControl_EnabledChanged);

            HideOnlyWhenClose = true;

            DockControl.Size = Size;
            DockControl.FloatingSize = Size;

            DockControl.Controls.Add(this);
            if (ParentModule != null && ParentModule.Icon != null)
            {
                DockControl.TabImage = ParentModule.Icon.ToBitmap().GetThumbnailImage(16, 16, null, IntPtr.Zero);
            }

            DockControl.PersistState = true;

            if (string.IsNullOrEmpty(Name))
            {
                Name = ToString();
            }

            DockControl.Name = "dc" + Name;

            blinkTimer = new System.Windows.Forms.Timer();
            blinkTimer.Interval = 500;
            blinkTimer.Tick += new EventHandler(blinkTimer_Tick);
            this.Enter += new EventHandler(DockingUserControl_Enter);
        }


        #endregion

        #region event handlers

        void DockingUserControl_Enter(object sender, EventArgs e)
        {
            blinkTimer.Stop();

            if (pParentModule != null && pParentModule.Icon != null)
                pDockControl.TabImage = pParentModule.Icon.ToBitmap().GetThumbnailImage(16, 16, null, IntPtr.Zero);

            Font o = pDockControl.Font;

            if (o.Bold)
            {
                pDockControl.Font = new Font(o, FontStyle.Regular);
            }
        }

        void blinkTimer_Tick(object sender, EventArgs e)
        {
            Font o = pDockControl.Font;

            if (o.Bold)
            {
                pDockControl.Font = new Font(o, FontStyle.Regular);
                if (pParentModule != null && pParentModule.Icon != null)
                {
                    pDockControl.TabImage = pParentModule.Icon.ToBitmap().GetThumbnailImage(16, 16, null, IntPtr.Zero);
                }
            }
            else
            {
                pDockControl.Font = new Font(o, FontStyle.Bold);
                if (pParentModule != null && pParentModule.Icon != null)
                {
                    pDockControl.TabImage = SBPweb.Presentation.Windows.Forms.Properties.Resources.Warning.ToBitmap().GetThumbnailImage(16, 16, null, IntPtr.Zero);
                }
            } 
           
        }

        void DockControl_Disposed(object sender, EventArgs e)
        {
            if (Disposed != null)
            {
                Disposed(sender, e);
            }
        }

        void DockControl_Closing(object sender, DockControlClosingEventArgs e)
        {
            if (Closing != null)
            {
                Closing(sender, e);
            }
        }

        void DockControl_Closed(object sender, EventArgs e)
        {
            base.Visible = false;

            if (Closed != null)
            {
                Closed(sender, e);
            }
        }

        void DockingUserControl_TextChanged(object sender, EventArgs e)
        {
            DockControl.TabText = DockControl.Text = Text;
        }

        protected virtual void DockControl_DockSituationChanged(object sender, EventArgs e)
        {
            if (sender != DockControl) return;

            if (DockControl.DockSituation == DockSituation.Document || DockControl.DockSituation == DockSituation.Docked || DockControl.DockSituation == DockSituation.Floating)
            {
                foreach (System.Windows.Forms.Control c in DockControl.Controls)
                {
                    c.Visible = true;
                }
            }
            if (DockControl.DockSituation == DockSituation.Floating)
            {
                //
                //  for all floating dockcontrols: set showintaskbar, set icon
                //
                if (DockControl.Parent != null && DockControl.Parent.Parent != null)
                {
                    System.Windows.Forms.Form g = DockControl.Parent.Parent as System.Windows.Forms.Form;
                    if (g != null)
                    {
                        g.ShowInTaskbar = true;
                        ////g.TopLevel = false;
                        g.TopMost = false;

                        if (!this.IsModal)
                            g.Owner = null;

                        ISmartpart isp = (DockControl.Controls[0] as ISmartpart);
                        IDockingSmartpart idsp = isp as IDockingSmartpart;
                        DockingUserControl duc = isp as DockingUserControl;
                        if (isp.ParentModule != null)
                        {
                            g.Icon = isp.ParentModule.Icon;
                        }
                        if (idsp != null)
                        {
                            g.FormBorderStyle = BorderStyleConverter.ModulesBorderStyleToWinFormsBorderStyle(idsp.BorderStyle);
                        }

                        if (!g.Visible)
                        {
                            g.MinimumSize = new Size((isp as System.Windows.Forms.Control).MinimumSize.Width + 50, (isp as System.Windows.Forms.Control).MinimumSize.Height + 50);//duc.FloatingMinimumSize;
                            g.MaximumSize = (isp as System.Windows.Forms.Control).MaximumSize;
                        }
                        else
                        {
                            g.BeginInvoke(new SetMinimumSizeHackHandler(SetMinimumSizeHack), g);
                        }
                    }
                }
            }

        }

        private delegate void SetMinimumSizeHackHandler(System.Windows.Forms.Control invokeControl);
        private void SetMinimumSizeHack(System.Windows.Forms.Control invokeControl)
        {
            if (invokeControl.InvokeRequired)
            {
                invokeControl.Invoke(new SetMinimumSizeHackHandler(SetMinimumSizeHack), invokeControl);
                return;
            }

            foreach (DockControl dc in DockControl.Manager.GetDockControls(DockSituation.Floating))
            {
                if (dc.Parent != null && dc.Parent.Parent != null)
                {
                    System.Windows.Forms.Form form = dc.Parent.Parent as System.Windows.Forms.Form;
                    if (form != null)
                    {
                        if (form.Controls[0].Controls.Count > 1)
                        {
                            form.MinimumSize = new Size();
                            form.MaximumSize = new Size();
                        }
                        else
                        {
                            form.MinimumSize = new Size(dc.Controls[0].MinimumSize.Width + 50, dc.Controls[0].MinimumSize.Height + 50);
                            form.MaximumSize = dc.Controls[0].MaximumSize;
                        }
                    }
                }
            }
        }

        void DockingUserControl_EnabledChanged(object sender, EventArgs e)
        {
            if (this.EnabledChanged != null)
            {
                this.EnabledChanged.Invoke(this, EventArgs.Empty);
            }
        }

        void DockingUserControl_VisibleChanged(object sender, EventArgs e)
        {
            if (this.VisibleChanged != null)
            {
                this.VisibleChanged.Invoke(this, EventArgs.Empty);
            }
        }

        #endregion

        #region Property accessors

        /// <summary>
        /// TD.SandDock.DockControl Instance. This is a container control instance. 
        /// Please Do not use this unless if necessary (and this case contact WBF team)
        /// </summary>
        public object DockControlInstance
        {
            get
            {
                return DockControl;
            }
        }

        /// <summary>
        /// Parent module of this control. this can be null.
        /// </summary>
        public IModule ParentModule
        {
            get
            {
                return pParentModule;
            }
        }

        /// <summary>
        /// Gets or sets the value indicatig whether the ISmartpart is displayed.
        /// </summary>
        public bool IsVisible
        {
            get
            {
                return base.Visible;
            }
            set
            {
                base.Visible = value;
                if (DockControl.Manager != null)
                {
                    if (value)
                    {
                        if (InitialAppearanceStyle == AppearanceStyle.Float)
                        {
                            DockControl.OpenFloating(WindowOpenMethod.OnScreenActivate);
                        }
                        else if (InitialAppearanceStyle == AppearanceStyle.Tabbed)
                        {
                            DockControl.OpenDocked(ContainerDockLocation.Center, WindowOpenMethod.OnScreenActivate);
                        }
                        else if (InitialAppearanceStyle == AppearanceStyle.Docked)
                        {
                            switch (InitialDock)
                            {
                                case System.Windows.Forms.DockStyle.Left:
                                    DockControl.OpenDocked(ContainerDockLocation.Left, WindowOpenMethod.OnScreenActivate);
                                    break;
                                case System.Windows.Forms.DockStyle.Top:
                                    DockControl.OpenDocked(ContainerDockLocation.Top, WindowOpenMethod.OnScreenActivate);
                                    break;
                                case System.Windows.Forms.DockStyle.Bottom:
                                    DockControl.OpenDocked(ContainerDockLocation.Bottom, WindowOpenMethod.OnScreenActivate);
                                    break;
                                default:
                                    DockControl.OpenDocked(ContainerDockLocation.Right, WindowOpenMethod.OnScreenActivate);
                                    break;
                            }
                        }
                    }
                    else
                    {
                        DockControl.Close();
                    }
                }
                if (this.VisibleChanged != null)
                {
                    this.VisibleChanged.Invoke(this, EventArgs.Empty);
                }
            }
        }

        /// <summary>
        /// Gets or sets the value indicatig whether the ISmartpart can respond to user interaction.
        /// </summary>
        public bool IsEnabled
        {
            get
            {
                return base.Enabled;
            }
            set
            {
                base.Enabled = value;
                if (this.EnabledChanged != null)
                {
                    this.EnabledChanged.Invoke(this, EventArgs.Empty);
                }
            }
        }

        /// <summary>
        /// Gets the value indicating whether the ISmartpart is displayed as a dialog form.
        /// This property has not got a fully support. Please use Modal DockingUserCOntrol
        /// </summary>
        [EditorBrowsable(EditorBrowsableState.Never)]
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Bindable(false)]
        public bool IsModal
        {
            get
            {
                return pIsModal;
            }
            protected set
            {
               pIsModal = value;
            }
        }

        /// <summary>
        /// Gets or sets the value indicating whether the smartpart is Tabbed, Docked or Float.
        /// </summary>
        public AppearanceStyle InitialAppearanceStyle
        {
            get
            {
                return pAppearanceStyle;
            }
            set
            {
                if (value == AppearanceStyle.Unknown)
                {
                    pAppearanceStyle = AppearanceStyle.Tabbed;
                }
                else
                {
                    pAppearanceStyle = value;
                }
            }
        }

        public System.Windows.Forms.DockStyle InitialDock
        {
            get
            {
                return pDockStyle;
            }
            set
            {
                pDockStyle = value;
                if (pDockStyle == System.Windows.Forms.DockStyle.Fill || pDockStyle == System.Windows.Forms.DockStyle.None)
                {
                    pDockStyle = System.Windows.Forms.DockStyle.Right;
                }
            }
        }

        /// <summary>
        /// Gets or sets the value indicating whether the smartpart is Tabbed, Docked or Float.
        /// </summary>
        public AppearanceStyle CurrentAppearanceStyle
        {
            get
            {
                if (DockControl.DockSituation == DockSituation.Docked) return AppearanceStyle.Docked;
                if (DockControl.DockSituation == DockSituation.Document) return AppearanceStyle.Tabbed;
                if (DockControl.DockSituation == DockSituation.Floating) return AppearanceStyle.Float;
                return AppearanceStyle.Unknown;
            }
        }

        public System.Windows.Forms.DockStyle DockLocation
        {
            get
            {
                switch (DockControl.MetaData.LastFixedDockSide)
                {
                    case ContainerDockLocation.Left: return System.Windows.Forms.DockStyle.Left;
                        //break;
                    case ContainerDockLocation.Bottom: return System.Windows.Forms.DockStyle.Bottom;
                        //break;
                    case ContainerDockLocation.Top: return System.Windows.Forms.DockStyle.Top;
                        //break;
                    case ContainerDockLocation.Right: return System.Windows.Forms.DockStyle.Right;
                        //break;
                    default: return System.Windows.Forms.DockStyle.None;
                        //break;
                }
            }
        }
 
        /// <summary>
        /// Gets or sets the smartpart allowing to be closed or not.
        /// </summary>
        public bool AllowClose
        {
            get
            {
                return DockControl.AllowClose;
            }
            set
            {
                DockControl.AllowClose = value;
            }
        }

        /// <summary>
        /// Gets or sets the smartpart allowing to be collapsed or not.
        /// </summary>
        public bool AllowCollapse
        {
            get
            {
                return DockControl.AllowCollapse;
            }
            set
            {
                DockControl.AllowCollapse = value;
            }
        }

        /// <summary>
        /// Gets or sets the smartpart allowing to be docked at the bottom or not.
        /// </summary>
        public bool AllowDockBottom
        {
            get
            {
                return DockControl.DockingRules.AllowDockBottom;
            }
            set
            {
                DockControl.DockingRules.AllowDockBottom = value;
            }
        }

        /// <summary>
        /// Gets or sets the smartpart allowing to be docked center or not.
        /// </summary>
        public bool AllowDockCenter
        {
            get
            {

                return DockControl.DockingRules.AllowTab;

            }
            set
            {

                DockControl.DockingRules.AllowTab = value;
            }
        }

        /// <summary>
        /// Gets or sets the smartpart allowing to be docked left or not.
        /// </summary>
        public bool AllowDockLeft
        {
            get
            {

                return DockControl.DockingRules.AllowDockLeft;

            }
            set
            {
                DockControl.DockingRules.AllowDockLeft = value;
            }
        }

        /// <summary>
        /// Gets or sets the smartpart allowing to be docked right or not.
        /// </summary>
        public bool AllowDockRight
        {
            get
            {

                return DockControl.DockingRules.AllowDockRight;
            }
            set
            {
                DockControl.DockingRules.AllowDockRight = value;
            }
        }

        /// <summary>
        /// Gets or sets the smartpart allowing to be docked to the top or not.
        /// </summary>
        public bool AllowDockTop
        {
            get
            {
                return DockControl.DockingRules.AllowDockTop;
            }
            set
            {
                DockControl.DockingRules.AllowDockTop = value;
            }
        }

        /// <summary>
        /// Gets or sets the smartpart allowing to be float or not.
        /// </summary>
        public bool AllowFloat
        {
            get
            {

                return DockControl.DockingRules.AllowFloat; ;
            }
            set
            {
                DockControl.DockingRules.AllowFloat = value;
            }
        }
		
        /// <summary>
        /// Gets or sets the smartpart to be collapsed or not.
        /// </summary>
        public bool Collapsed
        {
            get
            {
                return DockControl.Collapsed;
            }
            set
            {
                DockControl.Collapsed = value;
            }
        }

        /// <summary>
        /// Gets or sets the smartpart's location when it's floating.
        /// </summary>
        public Point FloatingLocation
        {
            get
            {

                return DockControl.FloatingLocation;
            }
            set
            {
                DockControl.FloatingLocation = value;
            }
        }

        /// <summary>
        /// Gets or sets the smartpart's size when it's floating.
        /// </summary>
        public Size FloatingSize
        {
            get
            {
                return DockControl.FloatingSize;
            }
            set
            {
                DockControl.FloatingSize = value;
            }
        }

        /// <summary>
        /// Gets or sets the smartpart's caption.
        /// </summary>
        public string Caption
        {
            get
            {
                return Text;
            }
            set
            {
                Text = DockControl.Text = DockControl.TabText = value;
            }
        }

        /// <summary>
        /// Gets or sets the smartpart to be hidden only if the close was hit or not.
        /// </summary>
        public bool HideOnlyWhenClose
        {
            get
            {
                return DockControl.CloseAction == DockControlCloseAction.HideOnly;
            }
            set
            {
                if (value)
                {
                    DockControl.CloseAction = DockControlCloseAction.HideOnly;
                }
                else
                {
                    DockControl.CloseAction = DockControlCloseAction.Dispose;
                }
            }
        }

        /// <summary>
        /// Gets or sets the smartpart to act as a window or not.
        /// </summary>
        public bool IsShowInWindowMenu
        {
            get
            {
                return mIsWindow;
            }
            set
            {
                mIsWindow = value;
            }
        }

        /// <summary>
        /// Gets or sets the smartpart's border style.
        /// </summary>
        public new BorderStyle BorderStyle
        {
            get
            {
                return mBorderStyle;
            }
            set
            {
                mBorderStyle = value;
                switch (value)
                {
                    case SBPweb.Modules.Smartparts.BorderStyle.Fixed3D:
                        pDockControl.BorderStyle = TD.SandDock.Rendering.BorderStyle.RaisedThick;
                        break;
                    case SBPweb.Modules.Smartparts.BorderStyle.FixedDialog:
                        pDockControl.BorderStyle = TD.SandDock.Rendering.BorderStyle.RaisedThick;
                        break;
                    case SBPweb.Modules.Smartparts.BorderStyle.FixedSingle:
                        pDockControl.BorderStyle = TD.SandDock.Rendering.BorderStyle.RaisedThin;
                        break;
                    case SBPweb.Modules.Smartparts.BorderStyle.FixedToolWindow:
                        pDockControl.BorderStyle = TD.SandDock.Rendering.BorderStyle.Flat;
                        break;
                    case SBPweb.Modules.Smartparts.BorderStyle.None:
                        pDockControl.BorderStyle = TD.SandDock.Rendering.BorderStyle.None;
                        break;
                    case SBPweb.Modules.Smartparts.BorderStyle.Sizable:
                        pDockControl.BorderStyle = TD.SandDock.Rendering.BorderStyle.RaisedThick;
                        break;
                    case SBPweb.Modules.Smartparts.BorderStyle.SizableToolWindow:
                        pDockControl.BorderStyle = TD.SandDock.Rendering.BorderStyle.RaisedThin;
                        break;
                }
            }
        }

        protected DockControl DockControl
        {
            get
            {

                if (pDockControl.IsDisposed || pDockControl.Disposing)
                {
                    throw new ObjectDisposedException("CloseAction of DockControl was Dispose can not be visible again.");
                    //DockControl newControl = new TabbedDocument();

                    //try
                    //{
                    //    newControl.CloseAction = pDockControl.CloseAction;
                    //    newControl.Text = newControl.TabText = Text;
                    //    newControl.FloatingSize = pDockControl.FloatingSize;
                    //    newControl.FloatingLocation = pDockControl.FloatingLocation;
                    //    newControl.DockedSize = pDockControl.DockedSize;
                    //    newControl.Collapsed = pDockControl.Collapsed;
                    //    newControl.AllowFloat = pDockControl.AllowFloat;
                    //    newControl.AllowDockTop = pDockControl.AllowDockTop;
                    //    newControl.AllowDockRight = pDockControl.AllowDockRight;
                    //    newControl.AllowDockLeft = pDockControl.AllowDockLeft;
                    //    newControl.AllowDockCenter = pDockControl.AllowDockCenter;
                    //    newControl.AllowDockBottom = pDockControl.AllowDockBottom;
                    //    newControl.AllowCollapse = pDockControl.AllowCollapse;
                    //    newControl.AllowClose = pDockControl.AllowClose;
                    //    newControl.Manager = ;
                    //}
                    //catch
                    //{
                    //    //do nothing :(
                    //}

                    //pDockControl = newControl;
                }
                return pDockControl;
            }
        }

        #endregion


        /// <summary>
        /// Makes visual notifycation
        /// </summary>
        public void NotifyUser()
        {
            NotifyUser(string.Empty, false);
        }

        /// <summary>
        /// Makes visual notification
        /// </summary>
        /// <param name="text">notification text;</param>
        public void NotifyUser(string text, bool forceBalloon)
        {
            if (!this.Focused &&
                (
                    (
                        pDockControl.Parent != null &&
                        pDockControl.Parent is TD.SandDock.DocumentContainer &&
                        pDockControl.Manager.ActiveTabbedDocument != null &&
                        pDockControl.Manager.ActiveTabbedDocument.Guid != pDockControl.Guid
                    ) ||
                    (
                        pDockControl.DockSituation == DockSituation.Docked && !pDockControl.IsOpen
                    )
                )
               )
            {
                blinkTimer.Start();
            }

            if (ParentForm != null && !ParentForm.ContainsFocus)
            {

                try
                {
                    SBPweb.Controls.Windows.FormNotifier.FlashWindowEx(ParentForm.Handle);
                }
                catch { }
            }

            if ((ParentForm != null && !ParentForm.ContainsFocus) || forceBalloon)
            {
                if (EnableTooltips && pParentModule != null && pParentModule.Host is System.Windows.Forms.Form)
                {
                    try
                    {
                        System.Windows.Forms.NotifyIcon ni = pParentModule.Host.GetType().GetProperty("NotifyIcon").GetValue(pParentModule.Host, null) as System.Windows.Forms.NotifyIcon;
                        ni.BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info;
                        ni.BalloonTipTitle = Caption;
                        if (!string.IsNullOrEmpty(text))
                        {
                            ni.BalloonTipText = text;
                        }
                        else
                            ni.BalloonTipText = " ";

                        ni.ShowBalloonTip(5000);
                    }
                    catch
                    {
                        //do nothing!!
                    }
                }
            }

        }

		private delegate void DisposeDelegate(bool disposing);

        protected override void Dispose(bool disposing)
        {
			if (this.InvokeRequired)
			{
				this.Invoke(new DisposeDelegate(Dispose), new object[] { disposing });
				return;
			}

            TextChanged -= new EventHandler(DockingUserControl_TextChanged);

            base.VisibleChanged -= new EventHandler(DockingUserControl_VisibleChanged);
            base.EnabledChanged -= new EventHandler(DockingUserControl_EnabledChanged);

			this.Enter -= new EventHandler(DockingUserControl_Enter);

			if (blinkTimer != null)
			{
				blinkTimer.Tick -= new EventHandler(blinkTimer_Tick);

				blinkTimer.Stop();
				blinkTimer.Dispose();
			}

            base.Dispose(disposing);
        }

        /// <summary>
        /// Occurs, when the IsVisible or Visible property changes.
        /// </summary>
        public new event EventHandler VisibleChanged;

        /// <summary>
        /// Occurs, when the IsEnabled or Enabled property changes.
        /// </summary>
        public new event EventHandler EnabledChanged;

        /// <summary>
        /// Occurs, before Smartpart closeing
        /// </summary>
        public event EventHandler Closing;

        /// <summary>
        /// Occurs, after Smartpart closeing
        /// </summary>
        public event EventHandler Closed;

        /// <summary>
        /// Occurs, after Smartpart disposing
        /// </summary>
        public event EventHandler Disposed;
    }

}
